//
//  GraphicsView.m
//  TestsQuartz2D
//
//  Created by mokai on 14-8-29.
//  Copyright (c) 2014年 mokai. All rights reserved.
//

/***
 
 总结:
 *导入CoreGraphics.framework
 *在drawRect中获得绘图上下文UIGraphicsGetCurrentContext
  图片上下文 UIGraphicsBeginImageContext。一般用于操作图片。然后UIGraphicsGetImageFromCurrentImageContext获得图片
 
 *全局设置
    设置一次，即可在当前上下文起作用，后续想改变再设置即可
    1、设置画笔颜色  UIColor set、setStroke、setFill 三者的区别在于 set优化级是最高的，调用set会导致stroke、fill都改变
    2、设置画笔宽度  CGContextSetLineWidth
 
 *各类path
     CGContextMoveToPoint        点
     CGContextAddLineToPoint	 直线，在点的基础上进行绘制
     CGContextAddEllipseInRect 	 椭圆
     CGContextAddArc		 	 弧
     CGContextAddRect            矩形
     绘制贝塞尔曲线
        CGContextAddQuadCurveToPoint   二次曲线
        CGContextAddCurveToPoint       三次曲线
 
 *绘制方式
    绘制path
        通过ContextAddXXXToPoint绘制path,基于current point
        通过ContextAddXXX绘制
    应用path
        CGContextStrokePath、CGContextFillPath
        CGContextDrawPath【使用这种方式可指定绘制模式，如绘制边框还是填充绘制】
 
  CAGradientLayer
  CABeizherPath
  CAShareLayer
 

 
 
 ***/
#import "GraphicsView.h"

@implementation GraphicsView


- (void)drawRect:(CGRect)rect
{
    //获取当前绘图上下文
    CGContextRef c = UIGraphicsGetCurrentContext();
    //开始路径
    //CGContextBeginPath(c);
    
    /**
     
     全局设置
     1、设置画笔颜色  UIColor set与setStroke、setFill的区别在于 set优化级是最高的，调用set会导致stroke、fill都改变
     2、设置画笔宽度  CGContextSetLineWidth
     
     **/
    [[UIColor redColor] set];
    
    UIFont *font = [UIFont boldSystemFontOfSize:15];
    
    [@"画线" drawInRect:CGRectMake(10, 20, 60, 40) withFont:font];
    [@"画矩形" drawInRect:CGRectMake(10, 50, 60, 40) withFont:font];
    [@"画圆" drawInRect:CGRectMake(10, 100, 60, 40) withFont:font];
    [@"图片：" drawInRect:CGRectMake(10, 150, 60, 40) withFont:font];
    [@"画贝塞尔曲线：" drawInRect:CGRectMake(10, 200, 120, 40) withFont:font];
    [@"画圆角矩形：" drawInRect:CGRectMake(10, 260, 100, 40) withFont:font];
    [[UIColor whiteColor] setFill];
    [[UIColor blueColor] setStroke];
    CGContextSetLineWidth(c, 2);
    
    
    
    
    /***
     
     1、绘制一条直线、弧线
     
     ***/
    CGContextMoveToPoint(c, 70, 30);//移动画笔
    CGContextAddLineToPoint(c, 100, 30);
    CGContextStrokePath(c);
    
    
    
    //也可以这样
    CGPoint sPoints1[2];
    sPoints1[0] = CGPointMake(110, 30);
    sPoints1[1] = CGPointMake(120, 40);
    CGContextAddLines(c, sPoints1, 2);
    CGContextDrawPath(c, kCGPathFillStroke);
    
    
    //画笑脸弧线
    //左
    CGContextMoveToPoint(c, 150, 30);//开始坐标p1
    //CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1,CGFloat x2, CGFloat y2, CGFloat radius)
    //x1,y1跟p1形成一条线的坐标p2，x2,y2结束坐标跟p3形成一条线的p3,radius半径,注意, 需要算好半径的长度,
    CGContextAddArcToPoint(c, 158, 18, 166, 30, 10);
    CGContextStrokePath(c);//绘画路径
    
    //右
    CGContextMoveToPoint(c, 170, 30);//开始坐标p1
    //CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1,CGFloat x2, CGFloat y2, CGFloat radius)
    //x1,y1跟p1形成一条线的坐标p2，x2,y2结束坐标跟p3形成一条线的p3,radius半径,注意, 需要算好半径的长度,
    CGContextAddArcToPoint(c, 178, 18, 186, 30, 10);
    CGContextStrokePath(c);//绘画路径
    
    //右
    CGContextMoveToPoint(c, 160, 40);//开始坐标p1
    //CGContextAddArcToPoint(CGContextRef c, CGFloat x1, CGFloat y1,CGFloat x2, CGFloat y2, CGFloat radius)
    //x1,y1跟p1形成一条线的坐标p2，x2,y2结束坐标跟p3形成一条线的p3,radius半径,注意, 需要算好半径的长度,
    CGContextAddArcToPoint(c, 168, 52, 176, 40, 10);
    CGContextStrokePath(c);//绘画路径
    
    
    /**
     
     2、矩形、一个正方形
     
     ***/
    CGContextAddRect(c, CGRectMake(100, 60, 10, 10));
    CGContextStrokePath(c);//描边
    
    CGContextAddRect(c, CGRectMake(120, 60, 10, 10));
    CGContextFillPath(c);//填充
    
    /*画三角形*/
    //只要三个点就行跟画一条线方式一样，把三点连接起来
    CGPoint sPoints[3];//坐标点
    sPoints[0] =CGPointMake(150, 60);//坐标1
    sPoints[1] =CGPointMake(140, 70);//坐标2
    sPoints[2] =CGPointMake(160, 70);//坐标3
    CGContextAddLines(c, sPoints, 3);//添加线
    CGContextClosePath(c);//封起来
    CGContextDrawPath(c, kCGPathFillStroke); //根据坐标绘制路径
    
    /***
     
     3、画圆、椭圆
     
     ****/
    CGContextAddEllipseInRect(c, CGRectMake(50, 100, 20, 20));
    CGContextStrokePath(c);
    
    CGContextAddEllipseInRect(c, CGRectMake(70, 100, 20, 30));
    CGContextFillPath(c);
    
    
    //void CGContextAddArc(CGContextRef c,CGFloat x, CGFloat y,CGFloat radius,CGFloat startAngle,CGFloat endAngle, int clockwise)
    //弧度＝180°/π （≈57.3°） 度＝弧度×180°/π 360°＝360×π/180 ＝2π 弧度
    // x,y为圆点坐标，radius半径，startAngle为开始的弧度，endAngle为 结束的弧度，clockwise 0为顺时针，1为逆时针。
    CGContextAddArc(c, 100, 100, 10,  -60 * 3.14 / 180, 90 * 3.14 / 180, 1);
    CGContextFillPath(c);
    
    /*
     
     4、图片
     
     core graphics层的原点是左下角，所以自然而然用CGContextDrawImage图像绘制的y方向也是在下边
     */
    UIImage *image = [UIImage imageNamed:@"test.jpeg"];
    [image drawInRect:CGRectMake(60, 150, 20, 20)];//在坐标中画出图片
    //[image drawAtPoint:CGPointMake(100, 340)];//保持图片大小在point点开始画图片，可以把注释去掉看看
    CGContextDrawImage(c, CGRectMake(100, 150, 20, 20), image.CGImage);//使用这个使图片上下颠倒了，参考http://blog.csdn.net/koupoo/article/details/8670024
    //CGContextDrawTiledImage(context, CGRectMake(0, 0, 20, 20), image.CGImage);//平铺图


    /*
     
     5、画贝塞尔曲线
     
     */
    //二次曲线
    CGContextMoveToPoint(c, 120, 200);//设置Path的起点
    CGContextAddQuadCurveToPoint(c,190, 230, 120, 250);//设置贝塞尔曲线的控制点坐标和终点坐标
    CGContextStrokePath(c);
    //三次曲线函数
    CGContextMoveToPoint(c, 200, 200);//设置Path的起点
    CGContextAddCurveToPoint(c,250, 180, 250, 240, 300, 220);//设置贝塞尔曲线的控制点坐标和控制点坐标终点坐标
    CGContextStrokePath(c);
    
    
    /*
     
     6、画圆角矩形
     
     */
    float fw = 180;
    float fh = 280;
    
    CGContextMoveToPoint(c, fw, fh-20);  // 开始坐标右边开始
    CGContextAddArcToPoint(c, fw, fh, fw-20, fh, 10);  // 右下角角度
    CGContextAddArcToPoint(c, 120, fh, 120, fh-20, 10); // 左下角角度
    CGContextAddArcToPoint(c, 120, 250, fw-20, 250, 10); // 左上角
    CGContextAddArcToPoint(c, fw, 250, fw, fh-20, 10); // 右上角
    CGContextClosePath(c);
    CGContextDrawPath(c, kCGPathFillStroke); //根据坐标绘制路径

    
    
    //矩形，并填弃渐变颜色
    //关于颜色参考http://blog.sina.com.cn/s/blog_6ec3c9ce01015v3c.html
    //http://blog.csdn.net/reylen/article/details/8622932
    //第一种填充方式，第一种方式必须导入类库quartcore并#import <QuartzCore/QuartzCore.h>，这个就不属于在context上画，而是将层插入到view层上面。那么这里就设计到Quartz Core 图层编程了。
    CAGradientLayer *gradient1 = [CAGradientLayer layer];
    gradient1.frame = CGRectMake(240, 120, 60, 30);
    gradient1.colors = [NSArray arrayWithObjects:(id)[UIColor whiteColor].CGColor,
                        (id)[UIColor grayColor].CGColor,
                        (id)[UIColor blackColor].CGColor,
                        (id)[UIColor yellowColor].CGColor,
                        (id)[UIColor blueColor].CGColor,
                        (id)[UIColor redColor].CGColor,
                        (id)[UIColor greenColor].CGColor,
                        (id)[UIColor orangeColor].CGColor,
                        (id)[UIColor brownColor].CGColor,nil];
    [self.layer insertSublayer:gradient1 atIndex:0];
    //第二种填充方式
    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    CGFloat colors[] =
    {
        1,1,1, 1.00,
        1,1,0, 1.00,
        1,0,0, 1.00,
        1,0,1, 1.00,
        0,1,1, 1.00,
        0,1,0, 1.00,
        0,0,1, 1.00,
        0,0,0, 1.00,
    };
    CGGradientRef gradient = CGGradientCreateWithColorComponents
    (rgb, colors, NULL, sizeof(colors)/(sizeof(colors[0])*4));//形成梯形，渐变的效果
    CGColorSpaceRelease(rgb);
    //画线形成一个矩形
    //CGContextSaveGState与CGContextRestoreGState的作用
    /*
     CGContextSaveGState函数的作用是将当前图形状态推入堆栈。之后，您对图形状态所做的修改会影响随后的描画操作，但不影响存储在堆栈中的拷贝。在修改完成后，您可以通过CGContextRestoreGState函数把堆栈顶部的状态弹出，返回到之前的图形状态。这种推入和弹出的方式是回到之前图形状态的快速方法，避免逐个撤消所有的状态修改；这也是将某些状态（比如裁剪路径）恢复到原有设置的唯一方式。
     */
    CGContextSaveGState(c);
    CGContextMoveToPoint(c, 220, 90);
    CGContextAddLineToPoint(c, 240, 90);
    CGContextAddLineToPoint(c, 240, 110);
    CGContextAddLineToPoint(c, 220, 110);
    CGContextClip(c);//context裁剪路径,后续操作的路径
    //CGContextDrawLinearGradient(CGContextRef context,CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint,CGGradientDrawingOptions options)
    //gradient渐变颜色,startPoint开始渐变的起始位置,endPoint结束坐标,options开始坐标之前or开始之后开始渐变
    CGContextDrawLinearGradient(c, gradient,CGPointMake
                                (220,90) ,CGPointMake(240,110),
                                kCGGradientDrawsAfterEndLocation);
    CGContextRestoreGState(c);// 恢复到之前的context
    
    //再写一个看看效果
    CGContextSaveGState(c);
    CGContextMoveToPoint(c, 260, 90);
    CGContextAddLineToPoint(c, 280, 90);
    CGContextAddLineToPoint(c, 280, 100);
    CGContextAddLineToPoint(c, 260, 100);
    CGContextClip(c);//裁剪路径
    //说白了，开始坐标和结束坐标是控制渐变的方向和形状
    CGContextDrawLinearGradient(c, gradient,CGPointMake
                                (260, 90) ,CGPointMake(260, 100),
                                kCGGradientDrawsAfterEndLocation);
    CGContextRestoreGState(c);// 恢复到之前的context
    
    //下面再看一个颜色渐变的圆
    CGContextDrawRadialGradient(c, gradient, CGPointMake(300, 100), 0.0, CGPointMake(300, 100), 10, kCGGradientDrawsBeforeStartLocation);


    
}


@end
